package org.iks.common.util;

import cn.hutool.core.date.DateUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.iks.common.ResultCode;
import org.iks.common.exception.BusinessException;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author kzou
 * @date 2023/12/30 11:38
 * @description:
 */
public class JwtUtil {

    private static final String secret = "rt2131231eeeaaeea2132131231saaaaaaaa23123123y1ubbbbbemamw912wa1dawawdaw21imbdadaknwdKBmwadaw52065461awdaw";

    public static final String PUBLIC_KEY = "publicKey";
    public static final String USER_ACCOUNT = "userAccount";
    public static final Integer expiration = 24 * 30 * 3;
    private static final byte[] keyBytes = Decoders.BASE64.decode(secret);
    private static final SecretKey key = Keys.hmacShaKeyFor(keyBytes);
    /**
     * 从数据声明生成令牌
     *
     * @param claims 数据声明
     * @return 令牌
     */
    public static String createToken(Map<String, Object> claims) {
        return Jwts.builder().claims(claims).expiration(DateUtil.offsetHour(new Date(), expiration))
                .signWith(key)
                .compact();
    }

    public static String createToken(String userAccount, String userPublicKey) {
        HashMap<String, Object> map = new HashMap<>();
        map.put(PUBLIC_KEY, userPublicKey);
        map.put(USER_ACCOUNT, userAccount);
        return createToken(userAccount, map);
    }

    public static String createToken(String subject, Map<String, Object> claims) {
        return Jwts
                .builder()
                .claims(claims)
                .subject(subject)
                .expiration(DateUtil.offsetHour(new Date(), expiration))
                .signWith(key)
                .compact();
    }

    /**
     * 从令牌中获取数据声明
     *
     * @param token 令牌
     * @return 数据声明
     */
    public static Claims tryParseToken(String token) {
        try {
            return Jwts
                    .parser()
                    .verifyWith(key)
                    .build()
                    .parseSignedClaims(token)
                    .getPayload();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 根据令牌获取用户账号
     *
     * @param token 令牌
     * @return 用户账号
     */
    public static String tryGetUserAccount(String token) {
        if (token == null) {
            return null;
        }
        Claims claims = tryParseToken(token);
        if (claims == null) {
            return null;
        }
        return claims.getSubject();
    }

    public static String getPublicKey(String token) {
        String res = tryGetUserAccount(token);
        if (res == null) {
            throw new BusinessException(ResultCode.LOGIN_OFFLINE);
        }
        return res;
    }

    public static String getUserAccount(String token) {
        String res = tryGetUserAccount(token);
        if (res == null) {
            throw new BusinessException(ResultCode.LOGIN_OFFLINE);
        }
        return res;
    }

    /**
     * 根据令牌获取用户地址
     *
     * @param token 令牌
     * @return 用户账号
     */
    public static String tryGetPublicKey(String token) {
        Claims claims = tryParseToken(token);
        if (claims == null) {
            return null;
        }
        return claims.get(PUBLIC_KEY, String.class);
    }

    public static boolean isValid(String token) {
        return tryParseToken(token) != null;
    }

}
